#if !USE_CONSOLE

#include "src/interface/renderPanel.h"

#include <iostream>

#define RAYTRACING 0
#define PHOTON_MAPPING 1

#include "src/scene/raytracing.h"
#include "src/scene/photonMapping.h"

RenderPanel::RenderPanel(QWidget* _parent, GLWidget *_gl) : QWidget(_parent), canvas(_gl){

//    std::cout <<"\n\nCriando painel" << std::endl;

	imageDlg = NULL;
    setSceneInImage();
//	imageDlg = new ImageDialog(this, canvas->getScene());
//    connect(canvas->getScene(), SIGNAL(setLine(unsigned int, uchar *)), imageDlg, SLOT(updateImageLine(unsigned int, uchar *)));
//    imageDlg->show();

    renderType = RAYTRACING;

    createLayout();
}

RenderPanel::~RenderPanel(){
//    std::cout <<"\n\nDeletando painel" << std::endl;
    clear();


}

void RenderPanel::clear(){
//    std::cout <<"\n\nClear em painel" << std::endl;

    if(renderRaytracingPushButton) delete renderRaytracingPushButton;
    if(renderPhotonsPushButton) delete renderPhotonsPushButton;
    if(emitPhotonsPushButton) delete emitPhotonsPushButton;
    if(hbbTreePushButton) delete hbbTreePushButton;

    if(photonMappingConeFilterConstantLabel) delete photonMappingConeFilterConstantLabel;
    if(photonMappingConeFilterConstantDoubleSpinBox) delete photonMappingConeFilterConstantDoubleSpinBox;

    if(raytracingGroupBox) delete raytracingGroupBox;
    if(photonMappingGroupBox) delete photonMappingGroupBox;

    if(imageDlg) delete imageDlg;

    delete layout();
    qDeleteAll(children());

    imageDlg = NULL;
}

void RenderPanel::createLayout()
{
    Scene *s = canvas->getScene();
    Raytracing *raytracing = s->getRaytracing();
    PhotonMapping *photonMapping = s->getPhotonMapping();


    hbbTreePushButton = new QPushButton(tr("HBBTree"));
    connect(hbbTreePushButton, SIGNAL(clicked()), this, SLOT(startHBBTree()));
    hbbTreePushButton->setEnabled(s->getObjectsSize() != 0);


    //------------------------------------------------------------------------
    //-----------------------------  RAYTRACING  -----------------------------
    //------------------------------------------------------------------------

    //-------------- profundidade
    QLabel *raytracingDepthLabel = new QLabel(QString("Profundidade: "));
    QSpinBox *raytracingDepthSpinBox = new QSpinBox;
    raytracingDepthSpinBox->setMinimum(1);
    raytracingDepthSpinBox->setMaximum(20);
    raytracingDepthSpinBox->setValue(raytracing->getDepth());
    connect(raytracingDepthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(changeRaytracingDepth(int)));

    QHBoxLayout *raytracingDepthLayout = new QHBoxLayout;
    raytracingDepthLayout->addWidget(raytracingDepthLabel);
    raytracingDepthLayout->addWidget(raytracingDepthSpinBox);
	raytracingDepthLayout->addStretch(1);



    //-------------- botão de renderizar
    renderRaytracingPushButton = new QPushButton(tr("Renderizar"));
    connect(renderRaytracingPushButton, SIGNAL(clicked()), this, SLOT(startRendering()));
    renderRaytracingPushButton->setDisabled(true);



    //-------------- grupo
    QVBoxLayout *raytracingLayout = new QVBoxLayout;
    raytracingLayout->addLayout(raytracingDepthLayout);
    raytracingLayout->addWidget(renderRaytracingPushButton);
	raytracingLayout->addStretch(1);

    raytracingGroupBox = new QGroupBox(QString::fromUtf8("Raytracing"));
    raytracingGroupBox->setLayout(raytracingLayout);

    //------------------------------------------------------------------------
    //---------------------------  PHOTON MAPPING  ---------------------------
    //------------------------------------------------------------------------

    //-------------- profundidade dos photons
    QLabel *photonMappingPhotonsDepthLabel = new QLabel(QString("Profundidade\ndos photons: "));
    QSpinBox *photonMappingPhotonsDepthSpinBox = new QSpinBox;
    photonMappingPhotonsDepthSpinBox->setMinimum(1);
    photonMappingPhotonsDepthSpinBox->setMaximum(20);
    photonMappingPhotonsDepthSpinBox->setValue(photonMapping->getPhotonDepth());
    connect(photonMappingPhotonsDepthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(changePhotonsDepth(int)));

    QHBoxLayout *photonMappingPhotonsDepthLayout = new QHBoxLayout;
    photonMappingPhotonsDepthLayout->addWidget(photonMappingPhotonsDepthLabel);
    photonMappingPhotonsDepthLayout->addWidget(photonMappingPhotonsDepthSpinBox);
	photonMappingPhotonsDepthLayout->addStretch(1);


    //-------------------------- GERAL
    //-------------- número de photons para emitir
    QLabel *photonMappingEmitMaxPhotonsLabel = new QLabel(QString("Emitir: "));
    QSpinBox *photonMappingEmitMaxPhotonsSpinBox = new QSpinBox;
    photonMappingEmitMaxPhotonsSpinBox->setMinimum(1);
    photonMappingEmitMaxPhotonsSpinBox->setMaximum(100000000);
    photonMappingEmitMaxPhotonsSpinBox->setSingleStep(1000);
    photonMappingEmitMaxPhotonsSpinBox->setValue(photonMapping->getMaxPhotons());
    connect(photonMappingEmitMaxPhotonsSpinBox, SIGNAL(valueChanged(int)), this, SLOT(changeEmitMaxPhotons(int)));

    QHBoxLayout *photonMappingEmitMaxPhotonsLayout = new QHBoxLayout;
    photonMappingEmitMaxPhotonsLayout->addWidget(photonMappingEmitMaxPhotonsLabel);
    photonMappingEmitMaxPhotonsLayout->addWidget(photonMappingEmitMaxPhotonsSpinBox);
	photonMappingEmitMaxPhotonsLayout->addStretch(1);


    //-------------- número de photons para a radiancia
    QLabel *photonMappingMaxNearestPhotonsLabel = new QLabel(QString::fromUtf8("Mais\npróximos: "));
    QSpinBox *photonMappingMaxNearestPhotonsSpinBox = new QSpinBox;
    photonMappingMaxNearestPhotonsSpinBox->setMinimum(1);
    photonMappingMaxNearestPhotonsSpinBox->setMaximum(100000);
    photonMappingMaxNearestPhotonsSpinBox->setSingleStep(10);
    photonMappingMaxNearestPhotonsSpinBox->setValue(photonMapping->getMaxNearestPhotons());
    connect(photonMappingMaxNearestPhotonsSpinBox, SIGNAL(valueChanged(int)), this, SLOT(changeMaxNearestPhotons(int)));

    QHBoxLayout *photonMappingMaxNearestPhotonsLayout = new QHBoxLayout;
    photonMappingMaxNearestPhotonsLayout->addWidget(photonMappingMaxNearestPhotonsLabel);
    photonMappingMaxNearestPhotonsLayout->addWidget(photonMappingMaxNearestPhotonsSpinBox);
	photonMappingMaxNearestPhotonsLayout->addStretch(1);


    //-------------- tamanho do raio maximo
    QLabel *photonMappingMaxRadiusLabel = new QLabel(QString::fromUtf8("Raio: "));
    QDoubleSpinBox *photonMappingMaxRadiusDoubleSpinBox = new QDoubleSpinBox;
    photonMappingMaxRadiusDoubleSpinBox->setMinimum(0.001);
    photonMappingMaxRadiusDoubleSpinBox->setMaximum(1000.0);
    photonMappingMaxRadiusDoubleSpinBox->setSingleStep(0.5);
    photonMappingMaxRadiusDoubleSpinBox->setDecimals(3);
    photonMappingMaxRadiusDoubleSpinBox->setValue(photonMapping->getMaxRadius());
    connect(photonMappingMaxRadiusDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(changeMaxRadius(double)));

    QHBoxLayout *photonMappingMaxRadiusLayout = new QHBoxLayout;
    photonMappingMaxRadiusLayout->addWidget(photonMappingMaxRadiusLabel);
    photonMappingMaxRadiusLayout->addWidget(photonMappingMaxRadiusDoubleSpinBox);
	photonMappingMaxRadiusLayout->addStretch(1);


    //-------------- grupo geral
    QVBoxLayout *photonMappingGeneralLayout = new QVBoxLayout;
    photonMappingGeneralLayout->addLayout(photonMappingEmitMaxPhotonsLayout);
    photonMappingGeneralLayout->addLayout(photonMappingMaxNearestPhotonsLayout);
    photonMappingGeneralLayout->addLayout(photonMappingMaxRadiusLayout);
	photonMappingGeneralLayout->addStretch(1);

    QGroupBox *photonMappingGeneralGroupBox = new QGroupBox(QString::fromUtf8("Geral"));
    photonMappingGeneralGroupBox->setLayout(photonMappingGeneralLayout);



    //-------------------------- CASUTICA
    //-------------- número de photons para emitir
    QLabel *photonMappingEmitCausticMaxPhotonsLabel = new QLabel(QString("Emitir: "));
    QSpinBox *photonMappingEmitCausticMaxPhotonsSpinBox = new QSpinBox;
    photonMappingEmitCausticMaxPhotonsSpinBox->setMinimum(1);
    photonMappingEmitCausticMaxPhotonsSpinBox->setMaximum(100000000);
    photonMappingEmitCausticMaxPhotonsSpinBox->setSingleStep(1000);
    photonMappingEmitCausticMaxPhotonsSpinBox->setValue(photonMapping->getCausticMaxPhotons());
    connect(photonMappingEmitCausticMaxPhotonsSpinBox, SIGNAL(valueChanged(int)), this, SLOT(changeEmitCausticMaxPhotons(int)));

    QHBoxLayout *photonMappingEmitCausticMaxPhotonsLayout = new QHBoxLayout;
    photonMappingEmitCausticMaxPhotonsLayout->addWidget(photonMappingEmitCausticMaxPhotonsLabel);
    photonMappingEmitCausticMaxPhotonsLayout->addWidget(photonMappingEmitCausticMaxPhotonsSpinBox);
	photonMappingEmitCausticMaxPhotonsLayout->addStretch(1);


    //-------------- número de photons para a radiancia
    QLabel *photonMappingCausticMaxNearestPhotonsLabel = new QLabel(QString::fromUtf8("Mais\npróximos: "));
    QSpinBox *photonMappingCausticMaxNearestPhotonsSpinBox = new QSpinBox;
    photonMappingCausticMaxNearestPhotonsSpinBox->setMinimum(1);
    photonMappingCausticMaxNearestPhotonsSpinBox->setMaximum(100000);
    photonMappingCausticMaxNearestPhotonsSpinBox->setSingleStep(10);
    photonMappingCausticMaxNearestPhotonsSpinBox->setValue(photonMapping->getCausticMaxNearestPhotons());
    connect(photonMappingCausticMaxNearestPhotonsSpinBox, SIGNAL(valueChanged(int)), this, SLOT(changeCausticMaxNearestPhotons(int)));

    QHBoxLayout *photonMappingCausticMaxNearestPhotonsLayout = new QHBoxLayout;
    photonMappingCausticMaxNearestPhotonsLayout->addWidget(photonMappingCausticMaxNearestPhotonsLabel);
    photonMappingCausticMaxNearestPhotonsLayout->addWidget(photonMappingCausticMaxNearestPhotonsSpinBox);
	photonMappingCausticMaxNearestPhotonsLayout->addStretch(1);


    //-------------- tamanho do raio maximo
    QLabel *photonMappingCausticMaxRadiusLabel = new QLabel(QString::fromUtf8("Raio: "));
    QDoubleSpinBox *photonMappingCausticMaxRadiusDoubleSpinBox = new QDoubleSpinBox;
    photonMappingCausticMaxRadiusDoubleSpinBox->setMinimum(0.001);
    photonMappingCausticMaxRadiusDoubleSpinBox->setMaximum(1000.0);
    photonMappingCausticMaxRadiusDoubleSpinBox->setSingleStep(0.5);
    photonMappingCausticMaxRadiusDoubleSpinBox->setDecimals(3);
    photonMappingCausticMaxRadiusDoubleSpinBox->setValue(photonMapping->getCausticMaxRadius());
    connect(photonMappingCausticMaxRadiusDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(changeCausticMaxRadius(double)));

    QHBoxLayout *photonMappingCausticMaxRadiusLayout = new QHBoxLayout;
    photonMappingCausticMaxRadiusLayout->addWidget(photonMappingCausticMaxRadiusLabel);
    photonMappingCausticMaxRadiusLayout->addWidget(photonMappingCausticMaxRadiusDoubleSpinBox);
	photonMappingCausticMaxRadiusLayout->addStretch(1);


    //-------------- grupo caustica
    QVBoxLayout *photonMappingCausticLayout = new QVBoxLayout;
    photonMappingCausticLayout->addLayout(photonMappingEmitCausticMaxPhotonsLayout);
    photonMappingCausticLayout->addLayout(photonMappingCausticMaxNearestPhotonsLayout);
    photonMappingCausticLayout->addLayout(photonMappingCausticMaxRadiusLayout);
	photonMappingCausticLayout->addStretch(1);

    QGroupBox *photonMappingCausticGroupBox = new QGroupBox(QString::fromUtf8("Cáustica"));
    photonMappingCausticGroupBox->setLayout(photonMappingCausticLayout);




    //-------------- filtro
    QLabel *photonMappingFilterTypeLabel = new QLabel(QString::fromUtf8("Filtro: "));
    QComboBox *photonMappingFilterTypeComboBox = new QComboBox;
    photonMappingFilterTypeComboBox->addItem(tr("Nenhum"));
    photonMappingFilterTypeComboBox->addItem(tr("Cone"));
    photonMappingFilterTypeComboBox->addItem(tr("Gaussiano"));
    photonMappingFilterTypeComboBox->setCurrentIndex(photonMapping->getFilter());
    connect(photonMappingFilterTypeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(changeFilterType(int)));

    QHBoxLayout *photonMappingFilterTypeLayout = new QHBoxLayout;
    photonMappingFilterTypeLayout->addWidget(photonMappingFilterTypeLabel);
    photonMappingFilterTypeLayout->addWidget(photonMappingFilterTypeComboBox);
	photonMappingFilterTypeLayout->addStretch(1);

    //-------------- constante do filtro de cone
    photonMappingConeFilterConstantLabel = new QLabel(QString::fromUtf8("Constante: "));
    photonMappingConeFilterConstantLabel->hide();
    photonMappingConeFilterConstantDoubleSpinBox = new QDoubleSpinBox;
    photonMappingConeFilterConstantDoubleSpinBox->hide();
    photonMappingConeFilterConstantDoubleSpinBox->setMinimum(1);
    photonMappingConeFilterConstantDoubleSpinBox->setMaximum(100);
    photonMappingConeFilterConstantDoubleSpinBox->setValue(photonMapping->getConeFilterConstant());
    connect(photonMappingConeFilterConstantDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(changeConeFilterConstant(double)));

    QHBoxLayout *photonMappingConeFilterConstantLayout = new QHBoxLayout;
    photonMappingConeFilterConstantLayout->addWidget(photonMappingConeFilterConstantLabel);
    photonMappingConeFilterConstantLayout->addWidget(photonMappingConeFilterConstantDoubleSpinBox);
	photonMappingConeFilterConstantLayout->addStretch(1);


    //-------------- grupo de filtro
    QVBoxLayout *photonMappingFilterLayout = new QVBoxLayout;
    photonMappingFilterLayout->addLayout(photonMappingFilterTypeLayout);
    photonMappingFilterLayout->addLayout(photonMappingConeFilterConstantLayout);
	photonMappingFilterLayout->addStretch(1);




    //-------------- teste
    QLabel *photonMappingtestReflexionLabel = new QLabel(QString::fromUtf8("Teste de\nreflexão: "));
    QComboBox *photonMappingtestReflexionComboBox = new QComboBox;
    photonMappingtestReflexionComboBox->addItem(tr("K's"));
    photonMappingtestReflexionComboBox->addItem(tr("Cores"));
    photonMappingtestReflexionComboBox->addItem(tr("Ambos"));
    photonMappingtestReflexionComboBox->setCurrentIndex(photonMapping->getTestReflexion());
    connect(photonMappingtestReflexionComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(changeTestReflexion(int)));


    //-------------- grupo de teste
    QHBoxLayout *photonMappingTestReflexionLayout = new QHBoxLayout;
    photonMappingTestReflexionLayout->addWidget(photonMappingtestReflexionLabel);
    photonMappingTestReflexionLayout->addWidget(photonMappingtestReflexionComboBox);
	photonMappingTestReflexionLayout->addStretch(1);



    //-------------- gardar primeira batida?
    QCheckBox *keepFirstBounceCheckBox = new QCheckBox("Guardar primeira\nbatida?");
    keepFirstBounceCheckBox->setChecked(photonMapping->getKeepFirstBounce());
    connect(keepFirstBounceCheckBox, SIGNAL(toggled(bool)), this, SLOT(changeKeepFirstBounce(bool)));


    //-------------- botão de emitir
    emitPhotonsPushButton = new QPushButton(QString::fromUtf8("Emitir fótons"));
    connect(emitPhotonsPushButton, SIGNAL(clicked()), this, SLOT(emitPhotons()));
    emitPhotonsPushButton->setDisabled(true);

    //-------------- botão de emitir
    renderPhotonsPushButton = new QPushButton(QString::fromUtf8("Renderizar fótons"));
    connect(renderPhotonsPushButton, SIGNAL(clicked()), this, SLOT(renderPhotons()));
    renderPhotonsPushButton->setDisabled(true);


    //-------------- grupo
    QVBoxLayout *photonMappingLayout = new QVBoxLayout;
    photonMappingLayout->addLayout(photonMappingPhotonsDepthLayout);
    photonMappingLayout->addWidget(photonMappingGeneralGroupBox);
    photonMappingLayout->addWidget(photonMappingCausticGroupBox);
    photonMappingLayout->addLayout(photonMappingFilterLayout);
    photonMappingLayout->addLayout(photonMappingTestReflexionLayout);
    photonMappingLayout->addWidget(keepFirstBounceCheckBox);
    photonMappingLayout->addWidget(emitPhotonsPushButton);
    photonMappingLayout->addWidget(renderPhotonsPushButton);
	photonMappingLayout->addStretch(1);

    photonMappingGroupBox = new QGroupBox(QString::fromUtf8("Photon Mapping"));
    photonMappingGroupBox->setLayout(photonMappingLayout);
    photonMappingGroupBox->hide();



    //-------------- layout principal
    QComboBox *renderTypeComboBox = new QComboBox;
    renderTypeComboBox->addItem(tr("Raytracing"));
    renderTypeComboBox->addItem(tr("Photon Mapping"));
    renderTypeComboBox->setCurrentIndex(RAYTRACING);
    connect(renderTypeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(changeRenderType(int)));


    QVBoxLayout *renderlayout = new QVBoxLayout;
    renderlayout->addWidget(photonMappingGroupBox);
    renderlayout->addWidget(raytracingGroupBox);
	renderlayout->addStretch(1);


    //------------------------------------------------------------
    QVBoxLayout *layout = new QVBoxLayout;
    layout->addWidget(hbbTreePushButton);
    layout->addWidget(renderTypeComboBox);
    layout->addLayout(renderlayout);
	layout->addStretch(1);

    setLayout(layout);
}

void RenderPanel::changeRaytracingDepth(int _d){
    canvas->getScene()->getRaytracing()->setDepth(_d);
    canvas->getScene()->getPhotonMapping()->setDepth(_d);
}

void RenderPanel::changePhotonsDepth(int _d){
    canvas->getScene()->getPhotonMapping()->setPhotonDepth(_d);
}

void RenderPanel::changeEmitMaxPhotons(int _d){
    canvas->getScene()->getPhotonMapping()->setMaxPhotons(_d);
}

void RenderPanel::changeMaxNearestPhotons(int _d){
    canvas->getScene()->getPhotonMapping()->setMaxNearestPhotons(_d);
}

void RenderPanel::changeMaxRadius(double _d){
    canvas->getScene()->getPhotonMapping()->setMaxRadius(_d);
}

void RenderPanel::changeEmitCausticMaxPhotons(int _d){
    canvas->getScene()->getPhotonMapping()->setCausticMaxPhotons(_d);
}

void RenderPanel::changeCausticMaxNearestPhotons(int _d){
    canvas->getScene()->getPhotonMapping()->setCausticMaxNearestPhotons(_d);
}

void RenderPanel::changeCausticMaxRadius(double _d){
    canvas->getScene()->getPhotonMapping()->setCausticMaxRadius(_d);
}

void RenderPanel::changeFilterType(int _d){
    canvas->getScene()->getPhotonMapping()->setFilter(_d);

    if(_d == CONE_FILTER)
    {
        photonMappingConeFilterConstantLabel->show();
        photonMappingConeFilterConstantDoubleSpinBox->show();
    }
    else
    {
        photonMappingConeFilterConstantLabel->hide();
        photonMappingConeFilterConstantDoubleSpinBox->hide();
    }
}

void RenderPanel::changeConeFilterConstant(double _d){
    canvas->getScene()->getPhotonMapping()->setConeFilterConstant(_d);
}

void RenderPanel::changeKeepFirstBounce(bool _b){
    canvas->getScene()->getPhotonMapping()->setKeepFirstBounce(_b);
}

void RenderPanel::changeTestReflexion(int _d){
    canvas->getScene()->getPhotonMapping()->setTestReflexion(_d);
}

void RenderPanel::changeRenderType(int _type){
    raytracingGroupBox->show();

    renderType = _type;

    if(renderType == RAYTRACING)
    {
        photonMappingGroupBox->hide();
    }
    else // == PHOTON_MAPPING
    {
        photonMappingGroupBox->show();
    }

}

void RenderPanel::startHBBTree(){
    hbbTreePushButton->setDisabled(true);
    canvas->getScene()->doHBBTree();
    canvas->updateGL();
}

void RenderPanel::startRendering(){
//    std::cout <<"\n\nComeçando a renderizar" << std::endl;

    //mandar criar uma imagem do tamanho correto
    //guardar e mostrar o dialog dela
    Camera *c = canvas->getScene()->getCamera();
    imageDlg->setImageSize(c->getM(), c->getN());
    imageDlg->show();

    //mandar renderizar na cena, e receber linha da imagem
    //fazer connect do dialog com a cena.
    if(renderType == RAYTRACING)
    {
        std::cout << "-------------Raytracing " << std::endl;
        canvas->getScene()->doRaytracing();
    }
    else // == PHOTON_MAPPING
    {
        std::cout << "-------------PhotonMapping" << std::endl;
        canvas->getScene()->doPhotonMapping();
    }
}

void RenderPanel::emitPhotons(){
    canvas->getScene()->doEmitPhotons(true);
}

void RenderPanel::renderPhotons(){

    Camera *c = canvas->getScene()->getCamera();
    imageDlg->setImageSize(c->getM(), c->getN());
    imageDlg->show();

    canvas->getScene()->doPhotonMapping(true);
}

void RenderPanel::setSceneInImage()
{
//    std::cout <<"\n\nAjeitando a iamgem" << std::endl;
//
//    if(imageDlg)
////    {
//        std::cout <<"TEM" << std::endl;
////        std::cout <<"\nDeletou a iamgem" << std::endl;
////        delete imageDlg;
////        imageDlg = NULL;
////    }
//    else std::cout <<"nao tem" << std::endl;

//    int nhe;
//    std::cin >> nhe;

	imageDlg = new ImageDialog(this, canvas->getScene());
//    imageDlg->show();
//	imageDlg->getImage()->setScene(canvas->getScene());
    connect(canvas->getScene(), SIGNAL(setLine(unsigned int, uchar *)), imageDlg, SLOT(updateImageLine(unsigned int, uchar *)));
}

#endif //!USE_CONSOLE

